home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
mint104s.zoo
/
mint.src
/
proc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-08
|
14KB
|
649 lines
/*
Copyright 1990,1991,1992 Eric R. Smith.
Copyright 1992 Atari Corporation.
All rights reserved.
*/
/* routines for handling processes */
#include "mint.h"
#include "xbra.h"
static void do_wakeup_things P_((void));
extern short proc_clock;
/* global process variables */
PROC *proclist; /* list of all active processes */
PROC *curproc; /* current process */
PROC *rootproc; /* pid 0 -- MiNT itself */
PROC *sys_q[NUM_QUEUES];
short time_slice = 2; /* default; actual value comes from mint.cnf */
#if 0
#define TIME_SLICE 2 /* number of 20ms ticks before process is
pre-empted */
#else
#define TIME_SLICE time_slice
#endif
/* macro for calculating number of missed time slices, based on a
* process' priority
*/
#define SLICES(pri) (((pri) >= 0) ? 0 : -(pri))
extern FILESYS bios_filesys;
/*
* get a new process struct
*/
PROC *
new_proc()
{
PROC *p;
void *pt;
pt = kmalloc(page_table_size + 16);
if (!pt) return 0;
p = (PROC *)kmalloc(SIZEOF(PROC));
if (!p) {
kfree(pt);
return 0;
}
/* page tables must be on 16 byte boundaries, so we
* round off by 16 for that; however, we will want to
* kfree that memory at some point, so we squirrel
* away the original address for later use
*/
p->page_table = ROUND16(pt);
p->pt_mem = pt;
return p;
}
/*
* dispose of an old proc
*/
void
dispose_proc(p)
PROC *p;
{
TRACELOW(("dispose_proc"));
kfree(p->pt_mem);
kfree(p);
}
/*
* create a new process that is (practically) a duplicate of the
* current one
*/
PROC *
fork_proc()
{
PROC *p;
int i;
FILEPTR *f;
long_desc *pthold;
void *ptmemhold;
if ((p = new_proc()) == 0) {
nomem:
DEBUG(("fork_proc: insufficient memory"));
mint_errno = ENSMEM; return 0;
}
/* child shares most things with parent, but hold on to page table ptr */
pthold = p->page_table;
ptmemhold = p->pt_mem;
*p = *curproc;
p->page_table = pthold;
p->pt_mem = ptmemhold;
/* these things are not inherited */
p->ppid = curproc->pid;
p->pid = newpid();
p->sigpending = 0;
p->sysstack = (long)(p->stack + STKSIZE - 12);
p->ctxt[CURRENT].ssp = p->sysstack;
p->ctxt[SYSCALL].ssp = (long)(p->stack + ISTKSIZE);
p->alarmtim = 0;
p->curpri = p->pri;
p->slices = SLICES(p->pri);
p->starttime = timestamp;
p->startdate = datestamp;
((long *)p->sysstack)[1] = FRAME_MAGIC;
((long *)p->sysstack)[2] = 0;
((long *)p->sysstack)[3] = 0;
p->usrtime = p->systime = p->chldstime = p->chldutime = 0;
/* copy open handles */
for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
if ((f = p->handle[i]) != 0) {
if (f->flags & O_NOINHERIT)
/* oops, we didn't really want to copy this handle */
p->handle[i] = 0;
else
f->links++;
}
}
/* copy root and current directories */
for (i = 0; i < NUM_DRIVES; i++) {
dup_cookie(&p->root[i], &curproc->root[i]);
dup_cookie(&p->curdir[i], &curproc->curdir[i]);
}
/* clear directory search info */
zero((char *)p->srchdta, NUM_SEARCH * SIZEOF(DTABUF *));
p->searches = 0;
/* copy memory */
p->mem = (MEMREGION **) kmalloc(p->num_reg * SIZEOF(MEMREGION *));
if (!p->mem) {
dispose_proc(p);
goto nomem;
}
p->addr = (virtaddr *)kmalloc(p->num_reg * SIZEOF(virtaddr));
if (!p->addr) {
kfree(p->mem);
dispose_proc(p);
goto nomem;
}
for (i = 0; i < curproc->num_reg; i++) {
p->mem[i] = curproc->mem[i];
if (p->mem[i] != 0)
p->mem[i]->links++;
p->addr[i] = curproc->addr[i];
}
/* now that memory ownership is copied, fill in page table */
init_page_table(p);
/* child isn't traced */
p->ptracer = 0;
p->ptraceflags = 0;
p->starttime = Tgettime();
p->startdate = Tgetdate();
p->q_next = 0;
p->wait_q = 0;
p->gl_next = proclist;
proclist = p; /* hook into the process list */
return p;
}
/*
* initialize the process table
*/
void
init_proc()
{
int i;
FILESYS *fs;
fcookie dir;
long_desc *pthold;
void *ptmemhold;
rootproc = curproc = new_proc();
assert(curproc);
pthold = curproc->page_table;
ptmemhold = curproc->pt_mem;
zero((char *)curproc, (long)sizeof(PROC));
curproc->page_table = pthold;
curproc->pt_mem = ptmemhold;
curproc->ppid = -1; /* no parent */
curproc->domain = DOM_TOS; /* TOS domain */
curproc->sysstack = (long) (curproc->stack+STKSIZE-12);
curproc->magic = CTXT_MAGIC;
curproc->memflags = F_PROT_S; /* default prot mode: super-only */
((long *)curproc->sysstack)[1] = FRAME_MAGIC;
((long *)curproc->sysstack)[2] = 0;
((long *)curproc->sysstack)[3] = 0;
/* NOTE: in main.c this could be changed, later */
curproc->base = _base;
strcpy(curproc->name, "MiNT");
/* get some memory */
curproc->mem = (MEMREGION **)kmalloc(NUM_REGIONS*SIZEOF(MEMREGION *));
curproc->addr = (virtaddr *)kmalloc(NUM_REGIONS*SIZEOF(virtaddr));
assert(curproc->mem && curproc->addr);
/* make sure it's filled with zeros */
zero((char *)curproc->addr, NUM_REGIONS * SIZEOF(virtaddr));
zero((char *)curproc->mem, NUM_REGIONS * SIZEOF(MEMREGION *));
curproc->num_reg = NUM_REGIONS;
/* get root and current directories for all drives */
for (i = 0; i < NUM_DRIVES; i++) {
if ((fs = drives[i]) != 0 && (*fs->root)(i, &dir) == E_OK) {
dup_cookie(&curproc->curdir[i], &dir);
curproc->root[i] = dir;
} else {
curproc->root[i].fs = curproc->curdir[i].fs = 0;
curproc->root[i].dev = curproc->curdir[i].dev = i;
}
}
init_page_table(curproc);
/* Set the correct drive. The current directory we
* set later, after all file systems have been loaded.
*/
curproc->curdrv = Dgetdrv();
proclist = curproc;
curproc->umask = 0;
/*
* some more protection against job control; unless these signals are
* re-activated by a shell that knows about job control, they'll have
* no effect
*/
curproc->sighandle[SIGTTIN] = curproc->sighandle[SIGTTOU] =
curproc->sighandle[SIGTSTP] = SIG_IGN;
/* set up some more per-process variables */
curproc->starttime = Tgettime();
curproc->startdate = Tgetdate();
if (has_bconmap)
curproc->bconmap = curbconmap;
else
curproc->bconmap = 1;
curproc->logbase = (void *)Logbase();
curproc->criticerr = *((long ARGS_ON_STACK (**) P_((long)))0x404L);
}
/*
* reset all process priorities to their base level
* called once per second, so that cpu hogs can get _some_ time
* slices :-).
*/
void
reset_priorities()
{
PROC *p;
for (p = proclist; p; p = p->gl_next) {
p->curpri = p->pri;
p->slices = SLICES(p->curpri);
}
}
/*
* more priority code stuff:
* run_next(p, slices): schedule process "p" to run next, with "slices"
* initial time slices; "p" does not actually start running until
* the next context switch
* fresh_slices(slices): give the current process "slices" more slices in
* which to run
*/
void
run_next(p, slices)
PROC *p;
int slices; /* BUG: currently ignored */
{
UNUSED(slices);
p->slices = 0;
p->curpri = MAX_NICE;
p->wait_q = READY_Q;
p->q_next = sys_q[READY_Q];
sys_q[READY_Q] = p;
}
void
fresh_slices(slices)
int slices;
{
curproc->slices = 0;
curproc->curpri = MAX_NICE+1;
proc_clock = slices;
}
/*
* add a process to a wait (or ready) queue.
*
* processes go onto a queue in first in-first out order
*/
void
add_q(que, proc)
int que;
PROC *proc;
{
PROC *q, **lastq;
/* "proc" should not already be on a list */
assert(proc->wait_q == 0);
assert(proc->q_next == 0);
lastq = &sys_q[que];
q = *lastq;
while(q) {
lastq = &q->q_next;
q = *lastq;
}
*lastq = proc;
proc->wait_q = que;
if (que != READY_Q) {
proc->curpri = proc->pri; /* reward the process */
proc->slices = SLICES(proc->curpri);
}
}
/*
* remove a process from a queue
*/
void
rm_q(que, proc)
int que;
PROC *proc;
{
PROC *q;
PROC *old = 0;
assert(proc->wait_q == que);
q = sys_q[que];
while (q && q != proc) {
old = q;
q = q->q_next;
}
if (q == 0)
FATAL("rm_q: unable to remove process from queue");
if (old)
old-